package com.nny.alarm.widget;

import com.uxwine.util.Log;

import android.graphics.Point;
import android.view.MotionEvent;

class HandGestureDetector
{
	HandView mView;
	Point mCenter;
	int mnRadius;
	boolean mbDragging;
	float mfBearing;
	
	public HandGestureDetector(HandView view)
	{
		mView = view;
		mCenter = new Point(0, 0);
		mbDragging = false;
	}
	
	public boolean onTouchEvent(MotionEvent event)
	{
		mCenter.x = mView.getMeasuredWidth() / 2;
		mCenter.y = mView.getMeasuredHeight() / 2;
		mnRadius = mView.mnRadius;
		if(event.getAction() == MotionEvent.ACTION_DOWN)
		{
			if(isIgnoreEvent(event.getX(), event.getY()))
				return false;
		}
		return handTouchEvent(event);
	}
	
	public boolean handTouchEvent(MotionEvent e)
	{
		int action = e.getAction();
		float x = e.getX();
		float y = e.getY();
		
		switch(action)
		{
		case MotionEvent.ACTION_DOWN:
		{
			if(!mView.isMarked(mfBearing))
			{
				mbDragging = false;
				return false;
			}
			mbDragging = true;
			onMarkerCaptured(x, y);
			break;
		}
		case MotionEvent.ACTION_MOVE:
		{
			if(mbDragging)
			{
				onMarkerMove(x, y);
			}
			break;
		}
		case MotionEvent.ACTION_CANCEL:
		case MotionEvent.ACTION_UP:
		{
			if(mbDragging)
			{
				onMarkerRelease();
				mbDragging = false;
			}
			break;
		}
		default:
			break;
		}
//		mView.invalidate();
		return true;
	}
	
	private void onMarkerMove(float x, float y)
	{
		mfBearing = calcBearing(x, y);
		mView.onMove(mfBearing);
	}
	
	private void onMarkerCaptured(float x, float y)
	{
		//mfBearing = calcBearing(x, y);	
		mView.onMove(mfBearing);	
	}
	
	private void onMarkerRelease()
	{
		mView.onMarked();
	}
	
	private boolean isIgnoreEvent(float x, float y)
	{
		float dx = x - mCenter.x;
		float dy = y - mCenter.y;
		final int w = mView.mnMarkWidth;

		if(mnRadius * mnRadius < dx * dx + dy * dy)
			return true;
		
		float bearing = calcBearing(x, y);
		if(!inArea(w, x, y, dx, dy, bearing))
			return true;
		
		mfBearing = bearing;
		return false;
	}
	
	private boolean inArea(float r, float x, float y, float dx, float dy, float angel)
	{
		float degree = 360.0f / (float)18; 
		
//		Log.d("zzm", String.format("a=%f,b=%f,degree=%f", angel, mfBearing, degree));
		final float min = mfBearing - degree;
		final float max = mfBearing + degree;
		
		float th = 360 - degree;
		if(min <= 0 && (angel > th || angel < max))
		{
			return true;
		}		
		return (angel < max && angel > min);
//		if(angel == 0 || angel == 360)
//		{
//			if(!((dx >= - r) && (dx <= r)))
//				return false;
//			return dy < 0;
//		}
//		if(angel == 90)
//		{
//			if(!((dy >= - r) && (dy <= r)))
//				return false;
//			return dx > 0;
//		}
//		
//		if(angel == 180)
//		{
//			if(! ((dx >= - r) && (dx <= r)))
//				return false;
//			return dy > 0;
//		}
//		
//		if(angel == 270)
//		{
//			if(! ((dy >= - r) && (dy <= r)))
//				return false;
//			return dx < 0;
//		}
//
//		
//		if(angel > 0 && angel < 90)
//		{
//			if(dx < 0 || dy > 0)
//				return false;
//			
//			double cotA = 1 / Math.tan((angel * Math.PI) / 180.0d);
//			double sinA = Math.sin(angel * Math.PI / 180.0d);
//			
//			return ((-dy - (cotA * dx - r / sinA) > 0) && (-dy - (cotA * dx + r / sinA) < 0));
//		}
//		else if(angel > 90 && angel < 180)
//		{
//			if(dx < 0 || dy < 0)
//				return false;
//			
//			double cotA = 1 / Math.tan((angel * Math.PI) / 180.0d);
//			double sinA = Math.sin(angel * Math.PI / 180.0d);
//			
//			return ((-dy - (cotA * dx - r / sinA) > 0) && (-dy - (cotA * dx + r / sinA) < 0));
//		}
//		else if(angel > 180 && angel < 270)
//		{
//			if(dx > 0 || dy < 0)
//				return false;
//			
//			angel -= 180;
//			double cotA = 1 / Math.tan((angel * Math.PI) / 180.0d);
//			double sinA = Math.sin(angel * Math.PI / 180.0d);
//			
//			return ((-dy - (cotA * dx - r / sinA) > 0) && (-dy - (cotA * dx + r / sinA) < 0));			
//		}
//		else if(angel > 270 && angel < 360)
//		{
//			if(dx > 0 || dy > 0)
//				return false;
//			
//			angel -= 180;
//			double cotA = 1 / Math.tan((angel * Math.PI) / 180.0d);
//			double sinA = Math.sin(angel * Math.PI / 180.0d);
//			
//			return ((-dy - (cotA * dx - r / sinA) > 0) && (-dy - (cotA * dx + r / sinA) < 0));
//		}
//		
//		return false;
	}
	
	
	protected float calcBearing(float x, float y) {

		double p = Math.atan2(mCenter.x - x, mCenter.y - y);
		if (p <= 0)
			return (float) (-p * 180 / Math.PI);
		else
			return (float) ((2 * Math.PI - p) * 180 / Math.PI);
	}	
}
